package me.sdevil507.org.service.impl;

import com.google.common.collect.Lists;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.extern.slf4j.Slf4j;
import me.sdevil507.biz.fruit.dto.ResultHomeListFruitDTO;
import me.sdevil507.biz.fruit.repository.FruitAuthorRepository;
import me.sdevil507.org.dto.ExpertSearchDto;
import me.sdevil507.org.dto.TempExpertDto;
import me.sdevil507.org.mapper.TempExpertMapper;
import me.sdevil507.org.po.*;
import me.sdevil507.org.repository.OrgRepository;
import me.sdevil507.org.repository.OrgUserRelRepository;
import me.sdevil507.org.repository.TempExpertRepository;
import me.sdevil507.org.service.OrgUserService;
import me.sdevil507.org.service.TempExpertService;
import me.sdevil507.supports.helper.Md5PasswordHelper;
import me.sdevil507.supports.jpa.PageParamsDTO;
import me.sdevil507.supports.jpa.SortParamsDTO;
import me.sdevil507.supports.shiro.helper.OrgAccountHelper;
import me.sdevil507.supports.util.AESUtil;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.transform.Transformers;
import org.hibernate.type.StandardBasicTypes;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.*;
import java.util.stream.Collectors;

/**
 * ApiUserServiceImpl
 *
 * @author sdevil507
 * created on 2019/12/15
 */
@Service
@Slf4j
public class TempExpertServiceImpl implements TempExpertService {
    @Autowired
    private TempExpertRepository tempExpertRepository;

    @Autowired
    private TempExpertMapper tempExpertMapper;

    @Autowired
    private Md5PasswordHelper md5PasswordHelper;

    @Autowired
    private OrgUserService orgUserService;

    @Autowired
    private OrgUserRelRepository orgUserRelRepository;

    @Autowired
    private OrgRepository orgRepository;

    @Autowired
    private FruitAuthorRepository fruitAuthorRepository;


    @Autowired
    JPAQueryFactory jpaQueryFactory;

    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public TempExpertPo readOneByPhoneNumber(String phoneNumber) {
        return tempExpertRepository.findByPhoneNumberAndDeletedIsFalse(phoneNumber);
    }

    @Override
    public boolean existsByPhoneNumber(String phoneNumber) {
        return tempExpertRepository.existsByPhoneNumberAndDeletedIsFalse(phoneNumber);
    }

    @Override
    public void updatePasswordByPhoneNumber(String newPassword, String phoneNumber) {
        tempExpertRepository.updatePasswordByPhoneNumber(newPassword, phoneNumber);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Long id) {
        // 当前操作用户的机构
        tempExpertRepository.logicDelete(id);
    }

    @Override
    public TempExpertPo create(TempExpertPo po) {
        po.setOrgID(OrgAccountHelper.getOrgId());
            //如果id存在则更新
        return tempExpertRepository.save(po);
    }

    /**
     * 判断姓名是否在本机构临时库下是否存在
     *
     * @param realName 手机号码
     * @param id          用户id
     * @param orgId       机构id
     * @return 执行反馈
     */
    @Override
    public boolean realNameExisted(String realName, Long id, Long orgId) {
        QTempExpertPo qTempExpertPo = QTempExpertPo.tempExpertPo;
        Predicate predicate = qTempExpertPo.id.isNotNull()
                .and(qTempExpertPo.realName.eq(realName))
                .and(qTempExpertPo.deleted.isFalse())
                .and(qTempExpertPo.orgID.eq(orgId));
        if (null != id) {
            predicate = ExpressionUtils.and(predicate, qTempExpertPo.id.ne(id));
        }
        return tempExpertRepository.exists(predicate);
    }


    @Override
    public List<TempExpertPo> readAll(TempExpertDto dto, SortParamsDTO sortParamsDto) {
        QTempExpertPo qTempExpertPo = QTempExpertPo.tempExpertPo;

        // 开启谓语查询条件
        Predicate predicate = qTempExpertPo.id.isNotNull()
                .and(qTempExpertPo.deleted.isFalse());

        //根据手机号码
        String phoneNumber = dto.getPhoneNumber();
        if (!StringUtils.isEmpty(phoneNumber)) {
            predicate = ExpressionUtils.and(predicate, qTempExpertPo.phoneNumber.like("%" + phoneNumber + "%"));
        }

        //根据姓名
        String realName = dto.getRealName();
        if (!StringUtils.isEmpty(realName)) {
            predicate = ExpressionUtils.and(predicate, qTempExpertPo.realName.like("%" + realName + "%"));
        }

        //根据组织查询
        Long orgid = dto.getOrgID();
        if (null != orgid && orgid.longValue() > 0) {
            predicate = ExpressionUtils.and(predicate, qTempExpertPo.orgID.eq(orgid));
        }

        //是否邀请
        String isInvite = dto.getInvited();
        if (!StringUtils.isEmpty(isInvite)) {
            predicate = ExpressionUtils.and(predicate, qTempExpertPo.invited.eq(isInvite));
        }


        // 排序
        Sort sort = sortParamsDto.getSort();
        if (null == sort) {
            sort = Sort.by(new Sort.Order(Sort.Direction.DESC, "createdDate"));
        }
        return Lists.newArrayList(tempExpertRepository.findAll(predicate, sort));
    }

    @Override
    public Page<TempExpertPo> readAllByPage(TempExpertDto dto, PageParamsDTO pageParamsDto, SortParamsDTO sortParamsDto) {
        QTempExpertPo qTempExpertPo = QTempExpertPo.tempExpertPo;

        // 开启谓语查询条件
        Predicate predicate = qTempExpertPo.id.isNotNull()
                .and(qTempExpertPo.deleted.isFalse());

        //根据手机号码
        String phoneNumber = dto.getPhoneNumber();
        if (!StringUtils.isEmpty(phoneNumber)) {
            predicate = ExpressionUtils.and(predicate, qTempExpertPo.phoneNumber.like("%" + phoneNumber + "%"));
        }

        //根据姓名
        String realName = dto.getRealName();
        if (!StringUtils.isEmpty(realName)) {
            predicate = ExpressionUtils.and(predicate, qTempExpertPo.realName.like("%" + realName + "%"));
        }

        //根据组织查询
        Long orgid = dto.getOrgID();
        if (null != orgid && orgid.longValue() > 0) {
            predicate = ExpressionUtils.and(predicate, qTempExpertPo.orgID.eq(orgid));
        }

        //是否邀请
        String isInvite = dto.getInvited();
        if (!StringUtils.isEmpty(isInvite)) {
            predicate = ExpressionUtils.and(predicate, qTempExpertPo.invited.eq(isInvite));
        }

        //是否验证通过
        String checked = dto.getChecked();
        if (!StringUtils.isEmpty(checked)) {
            predicate = ExpressionUtils.and(predicate, qTempExpertPo.checked.eq(checked));
        }


        // 排序
        Sort sort = sortParamsDto.getSort();
        if (null == sort) {
            sort = Sort.by(new Sort.Order(Sort.Direction.DESC, "createdDate"));
        }

        // 执行返回
        Pageable pageable = pageParamsDto.getPageableWithSort(sort);

        return tempExpertRepository.findAll(predicate, pageable);
    }

    @Override
    public Page<TempExpertPo> getInvited(TempExpertDto dto, PageParamsDTO pageParamsDto, SortParamsDTO sortParamsDto) {
        QTempExpertPo qTempExpertPo = QTempExpertPo.tempExpertPo;

        // 开启谓语查询条件
        Predicate predicate = qTempExpertPo.id.isNotNull()
                .and(qTempExpertPo.deleted.isFalse());

        //根据手机号码
        String phoneNumber = dto.getPhoneNumber();
        if (!StringUtils.isEmpty(phoneNumber)) {
            predicate = ExpressionUtils.and(predicate, qTempExpertPo.phoneNumber.like("%" + phoneNumber + "%"));
        }

        //根据姓名
        String realName = dto.getRealName();
        if (!StringUtils.isEmpty(realName)) {
            predicate = ExpressionUtils.and(predicate, qTempExpertPo.realName.like("%" + realName + "%"));
        }

        //根据组织查询
        Long orgid = OrgAccountHelper.getOrgId();
        if (null != orgid && orgid.longValue() > 0) {
            predicate = ExpressionUtils.and(predicate, qTempExpertPo.orgID.eq(orgid));
        }

        //是否邀请
        String isInvite = dto.getInvited();
        if (!StringUtils.isEmpty(isInvite)) {
            predicate = ExpressionUtils.and(predicate, qTempExpertPo.invited.eq(isInvite));
        }

        predicate = ExpressionUtils.and(predicate, qTempExpertPo.orgUserId.isNull());


        // 排序
        Sort sort = sortParamsDto.getSort();
        if (null == sort) {
            sort = Sort.by(new Sort.Order(Sort.Direction.DESC, "createdDate"));
        }

        // 执行返回
        Pageable pageable = pageParamsDto.getPageableWithSort(sort);

        return tempExpertRepository.findAll(predicate, pageable);
    }

    @Override
    public void resetPassword(Long id, String newPassword) {
        TempExpertPo tempExpertPo = tempExpertRepository.findById(id).orElse(null);
        if (null != tempExpertPo) {
            tempExpertRepository.resetPassword(id, AESUtil.encryptPassword(newPassword));
        }
    }

    @Override
    public List<TempExpertPo> readAllByOrg(ExpertSearchDto dto) {
        QTempExpertPo qTempExpertPo = QTempExpertPo.tempExpertPo;
        // 开启谓语查询条件
        Predicate predicate = qTempExpertPo.id.isNotNull()
                .and(qTempExpertPo.deleted.isFalse());
        //根据组织查询
        Long orgid = OrgAccountHelper.getOrgId();
        if (null != orgid && orgid.longValue() > 0) {
            predicate = ExpressionUtils.and(predicate, qTempExpertPo.orgID.eq(orgid));
        }

        //根据专家名称查询
        if(!StringUtils.isEmpty(dto.getAuthor())){
            predicate = ExpressionUtils.and(predicate, qTempExpertPo.realName.eq(dto.getAuthor()));
        }

        //根据手机号码进行查询
        if(!StringUtils.isEmpty(dto.getPhoneNumber())){
            predicate = ExpressionUtils.and(predicate, qTempExpertPo.phoneNumber.eq(dto.getPhoneNumber()));
        }
        // 执行Iterable转换List
        List<TempExpertPo> list = Lists.newArrayList(tempExpertRepository.findAll(predicate).iterator());
        return list;
    }

    @Override
    public  List<ExpertSearchDto> searchByName(ExpertSearchDto dto) {
        List<OrgUserRelPo> list= readAllExp(dto);
        List<TempExpertPo>  tempExpertPoList= readAllByOrg(dto);
        //返回给前台的dto类
        List<ExpertSearchDto> expertSearchDtoList =new ArrayList<>();
        if(null!=list && list.size()>0){
            for(OrgUserRelPo orgUserRelPo:list){
                ExpertSearchDto expertSearchDto= new ExpertSearchDto();
                if(null!=orgUserRelPo.getUser()){
                    expertSearchDto.setIsTemp(false);
                    expertSearchDto.setOrgUserId(orgUserRelPo.getUser().getId());
                    expertSearchDto.setPhoneNumber(orgUserRelPo.getUser().getPhoneNumber());
                    expertSearchDto.setAuthor(orgUserRelPo.getUser().getRealName());
                    expertSearchDtoList.add(expertSearchDto);
                }
            }
        }

        if(null!=tempExpertPoList && tempExpertPoList.size()>0){
            for(TempExpertPo tempExpertPo:tempExpertPoList){
                ExpertSearchDto expertSearchDto= new ExpertSearchDto();
                expertSearchDto.setIsTemp(true);
                expertSearchDto.setOrgUserId(tempExpertPo.getId());
                expertSearchDto.setAuthor(tempExpertPo.getRealName());
                expertSearchDto.setPhoneNumber(tempExpertPo.getPhoneNumber());
                expertSearchDtoList.add(expertSearchDto);
            }
        }

        return expertSearchDtoList;
    }

    @Override
    public void temporaryBecomeFormal(Long tmpId, Long orgUserId) {
        fruitAuthorRepository.temporaryBecomeFormal(tmpId,orgUserId);
        tempExpertRepository.deleteById(tmpId);
    }


    @Override
    public List<OrgUserRelPo> readAllExp(ExpertSearchDto dto) {
        QOrgUserRelPo qOrgUserRelPo = QOrgUserRelPo.orgUserRelPo;
        // 开启谓语查询条件
        Predicate predicate = qOrgUserRelPo.id.isNotNull();

        predicate = ExpressionUtils.and(predicate, qOrgUserRelPo.expert.isTrue());
        //根据组织查询
        if (null != dto.getOrgId() && dto.getOrgId().longValue() > 0) {
            predicate = ExpressionUtils.and(predicate, qOrgUserRelPo.org.id.eq(dto.getOrgId()));
        }
        //根据专家名称查询
        if(!StringUtils.isEmpty(dto.getAuthor())){
            predicate = ExpressionUtils.and(predicate, qOrgUserRelPo.user.realName.eq(dto.getAuthor().trim()));
        }

        //根据手机号码进行查询
        if(!StringUtils.isEmpty(dto.getPhoneNumber())){
            predicate = ExpressionUtils.and(predicate, qOrgUserRelPo.user.phoneNumber.eq(dto.getPhoneNumber()));
        }
        // 执行Iterable转换List
        List<OrgUserRelPo> list = Lists.newArrayList(orgUserRelRepository.findAll(predicate).iterator());
        return list;
    }

    @Override
    public List<ExpertSearchDto> findAllExpertOfOrg() {
        return findAllExpertsData(false);
    }


    @Override
    public List<ExpertSearchDto> findAllExpert(boolean isAll) {
        return findAllExpertsData(isAll);
    }


    public List<ExpertSearchDto> findAllExpertsData(boolean isAll) {
        Long orgId = null;
        if(!isAll){
            orgId = OrgAccountHelper.getOrgId();
        }
        String sql = "SELECT\n" +
                "       a.isTemp,\n" +
                "		a.author,\n" +
                "		a.orgUserId,\n" +
                "		a.phoneNumber \n" +
                "FROM\n" +
                "	(\n" +
                "	SELECT FALSE AS\n" +
                "		isTemp,\n" +
                "		bou.realname AS author,\n" +
                "		bou.id AS orgUserId,\n" +
                "		bou.phone_num AS phoneNumber \n" +
                "	FROM\n" +
                "		biz_org_user_rel bour\n" +
                "		LEFT JOIN user bou ON bour.user_id = bou.id \n" +
                "	WHERE\n" +
                "		bour.expert = 1 \n" +
                "		AND IF(ISNULL("+orgId+"), true, bour.org_id ="+orgId+" ) \n" +
                "		AND bou.deleted = 0 " +
                "UNION\n" +
                "	SELECT TRUE AS\n" +
                "		isTemp,\n" +
                "		bte.real_name AS author,\n" +
                "		bte.id AS orgUserId,\n" +
                "		bte.phone_number AS phoneNumber \n" +
                "	FROM\n" +
                "		biz_temp_expert bte \n" +
                "	WHERE\n" +
                "		IF(ISNULL("+orgId+"), true, bte.orgid ="+orgId+" ) \n" +
                "		AND bte.deleted = 0 \n" +
                "	) a \n" +
                "ORDER BY\n" +
                "	a.author";

        SQLQuery sqlQuery = entityManager.createNativeQuery(sql).unwrap(SQLQuery.class);
        sqlQuery.addScalar("isTemp", StandardBasicTypes.BOOLEAN);
        sqlQuery.addScalar("author", StandardBasicTypes.STRING);
        sqlQuery.addScalar("orgUserId", StandardBasicTypes.LONG);
        sqlQuery.addScalar("phoneNumber", StandardBasicTypes.STRING);
        Query query = sqlQuery.setResultTransformer(Transformers.aliasToBean(ExpertSearchDto.class));
        List<ExpertSearchDto> list = query.list();
        entityManager.clear();

        return list;

    }

    public Set<ExpertSearchDto> findAllExpertData(boolean isAll){
        ExpertSearchDto esearch = new ExpertSearchDto();
        if(!isAll){
            esearch.setOrgId(OrgAccountHelper.getOrgId());
        }
        List<OrgUserRelPo> pagePos = this.readAllExp(esearch);
        List<TempExpertPo>  tempExpertPoList= this.readAllByOrg(esearch);
        //返回给前台的dto类
        Set<ExpertSearchDto> expertSearchDtoList =new HashSet<>();
        if(null!=pagePos && pagePos.size()>0){
            for(OrgUserRelPo orgUserRelPo:pagePos){
                ExpertSearchDto expertSearchDto= new ExpertSearchDto();
                if(null!=orgUserRelPo.getUser()){
                    expertSearchDto.setIsTemp(false);
                    expertSearchDto.setOrgUserId(orgUserRelPo.getUser().getId());
                    expertSearchDto.setPhoneNumber(orgUserRelPo.getUser().getPhoneNumber());
                    expertSearchDto.setAuthor(orgUserRelPo.getUser().getRealName());
                    expertSearchDtoList.add(expertSearchDto);
                }
            }
        }
        if(null!=tempExpertPoList && tempExpertPoList.size()>0){
            for(TempExpertPo tempExpertPo:tempExpertPoList){
                ExpertSearchDto expertSearchDto= new ExpertSearchDto();
                expertSearchDto.setIsTemp(true);
                expertSearchDto.setOrgUserId(tempExpertPo.getId());
                expertSearchDto.setAuthor(tempExpertPo.getRealName());
                expertSearchDto.setPhoneNumber(tempExpertPo.getPhoneNumber());
                expertSearchDtoList.add(expertSearchDto);
            }
        }
        //按姓名排序
        expertSearchDtoList = expertSearchDtoList.stream().sorted(Comparator.comparing(ExpertSearchDto::getAuthor)).collect(Collectors.toSet());

        return  expertSearchDtoList;
    }

    /*    //注册用户
    @Override
    public void register(TempExpertDto dto)  throws PhoneNumberExistedException {
        if (null!=dto.getId() && dto.getId()>0) {

           OrgUserPo orgUserPo= orgUserService.readOneByPhoneNumber(dto.getPhoneNumber());
            if(null!=orgUserPo){
                //todo 如果专家已存在，应该怎么处理
            }else{
                // 如果是新增,判断手机号码在机构下是否存在，如果存在
                if (phoneNumberExisted(dto.getPhoneNumber(), null, dto.getOrgID())) {
                    throw new PhoneNumberExistedException("手机号码已经被邀请，请联系管理员进行审核!");
                }else{
                    //如果id存在则更新
                    tempExpertRepository.save(tempExpertMapper.dto2po(dto));
                }
            }

        }

    }*/


}
